package commandLogic;

import java.text.DateFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;

import exceptions.CommandCouldNotBeParsedException;

import utilities.Command;
import utilities.CommandAdd;
import utilities.CommandMark;
import utilities.CommandType;
import utilities.Task;

public class CommandParser {
	
	private static final String MESSAGE_ERROR_INVALID_FORMAT = "Invalid command. Please follow correct format";
	
	private static final String [] LIST_ADD_SYNONYMS = {"add", "insert", "create", "new"};
	private static final String [] LIST_MARK_SYNONYMS = {"mark", "delete", "del", "remove", "discard", "erase", "drop"};
	private static final String [] LIST_EDIT_SYNONYMS = {"update", "edit", "change", "alter", "modify"};
	private static final String [] LIST_REDO_SYNONYMS = {"redo"};
	private static final String [] LIST_UNDO_SYNONYMS = {"undo"};
	private HashMap<String, CommandType> dictionary;
	
	private int _parsingPhase;
	private String _inputText;
	private CommandType _commandType;
	private Task _taskToBeAdded;
	private Command _parsedCommand;
	private Date _date;

	private static final int FIRST_WORD = 0;
	private static final String JIMI_DATE_FORMAT = "\"dd/MM/yyyy \'at\' HH:mm\"";
	
	public CommandParser(){
		
		initialiseDictionary();
		_parsingPhase = 0;
	
	}
	
	private void initialiseDictionary() {
		dictionary = new HashMap<String, CommandType>();
		for(String entry : LIST_ADD_SYNONYMS){
			dictionary.put(entry, CommandType.ADD);
		}
		for(String entry :  LIST_EDIT_SYNONYMS){
			dictionary.put(entry, CommandType.EDIT);
		}
		for(String entry :  LIST_MARK_SYNONYMS){
			dictionary.put(entry, CommandType.MARK);
		}
		for(String entry :  LIST_UNDO_SYNONYMS){
			dictionary.put(entry, CommandType.UNDO);
		}
		for(String entry :  LIST_REDO_SYNONYMS){
			dictionary.put(entry, CommandType.REDO);
		}
	}
	
	//InputText format should be "ADD 22/12/1990 at 05:33 HAHAHAHA Task Name goes here"
	public Command parseCommand(String inputText) throws CommandCouldNotBeParsedException {
		
		_parsingPhase = 1;
		_inputText = inputText;
		
		String currentText = inputText;
		
		try {
			currentText = parseCommandTypeFirst(currentText);
			
			currentText = parseDateSecond(currentText);
			
			currentText = parseCommandThird(currentText);
			
		} catch  (IllegalAccessException e){
			
			e.printStackTrace();
		}
		

		
		switch (_commandType) {
		case ADD:
			_parsedCommand = new CommandAdd(_inputText, _taskToBeAdded);
			break;
		case EDIT:
			_parsedCommand = null; //TODO Work in progress
			break;
		case MARK:
			_parsedCommand = new CommandMark(_inputText, _taskToBeAdded);
			break;
		case SEARCH:
			_parsedCommand = null; //TODO Work in progress
			break;
		case UNDO:
			_parsedCommand = null; //TODO Work in progress
			break;
		case REDO:
			_parsedCommand = null; //TODO Work in progress
			break;
		}
		return _parsedCommand;
	}
	
	private String parseCommandTypeFirst(String textToBeParsed) throws CommandCouldNotBeParsedException, IllegalAccessException{
		
		if (_parsingPhase != 1){
			throw new IllegalAccessException("Command Type is not first to be parsed"); 
		}
		
		String parsedText;
		String tokenisedText[] = textToBeParsed.split(" ");
		String firstToken = tokenisedText[FIRST_WORD].toLowerCase();
		
		if(dictionary.containsKey(firstToken)){
			
			_commandType = dictionary.get(firstToken);
			parsedText = textToBeParsed.substring(firstToken.length());
			parsedText.trim();			
			
		}
		
		else {
			throw new CommandCouldNotBeParsedException(MESSAGE_ERROR_INVALID_FORMAT);
		}
		
		_parsingPhase++;
		return parsedText;
	}
	
	
	private String parseDateSecond(String textToBeParsed) throws IllegalAccessException, CommandCouldNotBeParsedException{
		
		if (_parsingPhase != 2){
			throw new IllegalAccessException("Date is not second to be parsed"); 
		}
		
		String parsedText;
		ParsePosition currentDateParsePosition = new ParsePosition(0);
		SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy 'at' HH:mm");
		
		_date = dateFormat.parse(textToBeParsed, currentDateParsePosition);
		
		if(_date == null){
			throw new CommandCouldNotBeParsedException(MESSAGE_ERROR_INVALID_FORMAT);
		}
		System.out.println("THIS PARSED DATE IS " + _date.toString());
		parsedText = textToBeParsed.substring(currentDateParsePosition.getIndex());
		parsedText.trim();
		
		_parsingPhase++;
		
		return parsedText;
	}
	
	private String parseCommandThird(String textToBeParsed) throws IllegalAccessException{
		
		if (_parsingPhase != 3){
			throw new IllegalAccessException("Remaining text is not third to be parsed"); 
		}
		
		_parsingPhase++;
		
		_taskToBeAdded = new Task(textToBeParsed, _date);
		
		return textToBeParsed;
		
	}
	
	public CommandType getCommandType(){
		return _commandType;
	}
	
	public Date getDate(){
		return _date;
	}
	
	public Command getCommand(){
		return _parsedCommand;
	}
	
	
}
